import got from 'got';
import SpotifyWebApi from 'spotify-web-api-node';
import pMap from 'p-map';
import signale from '../lib/signale';
import {isrc2deezer} from './deezer';
import type {playlistInfo, trackType} from 'd-fi-core/dist/types';

// type spotifyTypes = 'track' | 'episode' | 'album' | 'artist' | 'playlist' | 'show';

type tokensType = {
  clientId: string;
  accessToken: string;
  accessTokenExpirationTimestampMs: number;
  isAnonymous: true;
};

const getOffset = (next: null | string): number => {
  if (next) {
    const o = next.split('&').find((p) => p.includes('offset='));
    return o ? Number(o.split('=')[1]) : 0;
  }

  return 0;
};

export const spotifyApi = new SpotifyWebApi();

export const spotifyPlaylist2Deezer = async (id: string): Promise<[playlistInfo, trackType[]]> => {
  console.log(signale.info('Fetching spotify playlist. Please hold on.'));
  const {body} = await spotifyApi.getPlaylist(id);
  let offset = getOffset(body.tracks.next);
  let tracks: trackType[] = [];

  const mapper = async (item: SpotifyApi.PlaylistTrackObject, index: number) => {
    try {
      if (item.track) {
        const track = await isrc2deezer(item.track.name, item.track.external_ids.isrc);
        // console.log(signale.success(`Track #${index}: ${item.track.name}`));
        track.TRACK_POSITION = index + 1;
        tracks.push(track);
      }
    } catch (err) {
      console.error(signale.error(`Track #${index}: ${item.track.name}`));
      console.error(signale.note(err.message));
    }
  };
  await pMap(body.tracks.items, mapper, {concurrency: 25});

  while (offset !== 0) {
    const {body} = await spotifyApi.getPlaylistTracks(id, {limit: 100, offset: offset ? offset : 0});
    offset = getOffset(body.next);
    await pMap(body.items, mapper, {concurrency: 25});
  }

  const dateCreated = new Date().toISOString();
  const playlistInfoData: playlistInfo = {
    PLAYLIST_ID: body.id,
    PARENT_USERNAME: body.owner.id,
    PARENT_USER_ID: body.owner.id,
    PICTURE_TYPE: 'cover',
    PLAYLIST_PICTURE: body.images[0].url,
    TITLE: body.name,
    TYPE: '0',
    STATUS: '0',
    USER_ID: body.owner.id,
    DATE_ADD: dateCreated,
    DATE_MOD: dateCreated,
    DATE_CREATE: dateCreated,
    NB_SONG: body.tracks.total,
    NB_FAN: 0,
    CHECKSUM: body.id,
    HAS_ARTIST_LINKED: false,
    IS_SPONSORED: false,
    IS_EDITO: false,
    __TYPE__: 'playlist',
  };

  console.log(signale.info('Total matched tracks --> ' + tracks.length));
  return [playlistInfoData, tracks];
};

export const spotifyArtist2Deezer = async (id: string): Promise<trackType[]> => {
  // Artist tracks are limited to 10 items
  console.log(signale.info("Fetching spotify artist tracks. Shouln't take long. Maxium 10 tracks."));
  const {body} = await spotifyApi.getArtistTopTracks(id, 'GB');
  const tracks: trackType[] = [];
  await pMap(
    body.tracks,
    async (item, index) => {
      try {
        const track = await isrc2deezer(item.name, item.external_ids.isrc);
        // console.log(signale.success(`Track #${index}: ${item.name}`));
        tracks.push(track);
      } catch (err) {
        console.error(signale.error(`Track #${index}: ${item.name}`));
        console.error(signale.note(err.message));
      }
    },
    {concurrency: 10},
  );
  return tracks;
};

export const setSpotifyAnonymousToken = async () => {
  const tokens: tokensType = await got(
    'https://open.spotify.com/get_access_token?reason=transport&productType=embed',
  ).json();
  spotifyApi.setAccessToken(tokens.accessToken);
};
